package com.hex.ds.em.hcdp.gauss.analyze.script.performance;

import static com.hex.ds.em.hcdp.gauss.pack.service.impl.ScriptPackTaskServiceImpl.wordResult;

import com.hex.ds.em.hcdp.basic.common.IResultForReport;
import com.hex.ds.em.hcdp.gauss.analyze.script.performance.entity.CheckSubstrEntity;
import com.hex.ds.em.hcdp.gauss.common.entity.ScriptPackScanResultEntity;
import com.hex.ds.em.hcdp.gauss.common.enums.AntlrEnum;
import com.hex.hdtp.common.utils.AntlrUtil;
import com.hex.hlrt.gauss.g4.basic.gen.GaussParser.Join_clauseContext;
import com.hex.hlrt.gauss.g4.basic.gen.GaussParser.Select_statementContext;
import com.hex.hlrt.gauss.g4.basic.gen.GaussParser.Unary_logical_expressionContext;
import com.hex.hlrt.gauss.g4.basic.gen.GaussParser.Where_clauseContext;
import com.hex.hlrt.gauss.g4.basic.gen.GaussParserBaseListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

/**
 * @Package com.hex.ds.em.hcdp.gauss.analyze.script.performance
 * @ClassName CheckSubstrListener
 * @Description substr 检查
 * @Author gj.xu
 * @Date 2024/9/14 15:52
 * @Version v2.0
 **/
@Slf4j
@Accessors(chain = true)
@Scope(value = "prototype")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Service("Gauss-CheckSubstr")
public class CheckSubstrListener extends GaussParserBaseListener implements
    IResultForReport {

  @Override
  public void exitUnary_logical_expression(Unary_logical_expressionContext ctx) {
    //对SUBSTR()进行特殊处理
    if (AntlrUtil.queryDesignateParent(ctx, Where_clauseContext.class) || AntlrUtil
        .queryDesignateParent(ctx, Join_clauseContext.class, Select_statementContext.class)) {
      String str = ctx.getText().trim().toUpperCase();
      //判断关联符号是否为=
      if (str.matches("SUBSTR\\s*\\(.*") && str.matches(".*\\)\\s*=.*")) {
        //截取SUBSTR(...)
        Pattern pattern = Pattern.compile("SUBSTR\\s*\\((.*?)\\)");
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
          String substrPart = "SUBSTR(" + matcher.group(1) + ")";
          List<String> arguments = extractArguments(substrPart);
          //格式是否满足substr（字段，1，n）
          boolean isFormatSatisfied = arguments.size() == 3 && checkForFieldInArguments(
              Arrays.asList(arguments.get(0).split(",")))
              && arguments.get(1).equals("1") &&arguments.get(2).matches("\\d+");

          if (isFormatSatisfied) {
            setResultForWordReport();
            CheckSubstrEntity ruleEntity = new CheckSubstrEntity();
            ctx.addHeadAnyChild(ruleEntity);
            log.info("rule-[CheckSubstr]:");
          }
        }

      }

    }
  }

  /**
   * @Method extractArguments <br>
   * @Param String functionCall<br>
   * @Return List<String> <br>
   * @Description 分割函数的参数 <br>
   * @Author sf.zheng<br>
   * @Date 2024/9/19 16:44  <br>
   * @Version V1.0<br>
   */
  private List<String> extractArguments(String functionCall) {
    List<String> arguments = new ArrayList<>();
    Pattern pattern = Pattern.compile("\\((.*?)\\)");
    Matcher matcher = pattern.matcher(functionCall);
    if (matcher.find()) {
      String argsStr = matcher.group(1);
      int start = 0;
      int openBrackets = 0;
      for (int i = 0; i < argsStr.length(); i++) {
        if (argsStr.charAt(i) == '(') {
          openBrackets++;
        } else if (argsStr.charAt(i) == ')') {
          openBrackets--;
        } else if (openBrackets == 0 && argsStr.charAt(i) == ',') {
          arguments.add(argsStr.substring(start, i).trim());
          start = i + 1;
        }
      }
      arguments.add(argsStr.substring(start).trim());
    }
    return arguments;
  }

  /**
   * @Method checkForFieldInArguments <br>
   * @Param List<String> arguments <br>
   * @Return boolean <br>
   * @Description 检查参数是否包含字段 <br>
   * @Author sf.zheng<br>
   * @Date 2024/9/19 17:25 <br>
   * @Version V1.0<br>
   */
  private boolean checkForFieldInArguments(List<String> arguments) {
    for (String argument : arguments) {
      if (!argument.startsWith("'") && !argument.startsWith("\"") && !Pattern
          .matches("^[0-9].*", argument)
          && !argument.contains("(")) {
        return true;
      }
    }
    return false;
  }


  @Override
  public void setResultForWordReport() {
    ScriptPackScanResultEntity result = wordResult
        .get(AntlrEnum.SUBSTR_CHECK.getValue());
    if (result == null) {
      return;
    }
    result.setScanTable("").setScanState("fail");
    wordResult.put(AntlrEnum.SUBSTR_CHECK.getValue(), result);
  }
}
